<?php
namespace core\models;
/**
 * 数据库查询分页类
 * @package 扩展库
 * @subpackage 分页类
 * @author osCommerce
 */
class splitPageResults {
    public $sql_query;
    /**
     * 总记录数
     * @var int
     */
    public $number_of_rows;
    /**
     * 当前在第几页
     * @var int
     */
    public $current_page_number;
    /**
     * 总页数
     * @var int
     */
    public $number_of_pages;
    /**
     * 每页显示几个页码
     * @var int
     */
    public $number_of_rows_per_page;
    /**
     * 翻页的GET参数名称，默认是page
     * @var string
     */
    public $page_name;

    /* class constructor */
    /**
     * 数据库查询分页类
     * @param SQL $query 原始的SQL代码
     * @param int $max_rows 每页最大显示多少条记录
     * @param string $count_key count(*) 中间那个字段
     * @param string $page_holder 翻页参数名称
     * @param Database_Action $db 数据库连接，如果不传，参初始化默认数据库
     * @return splitPageResults
     */
    function __construct(&$query, $max_rows, $count_key = '*', $page_holder = 'page', Database_Action $db = null) {
        if ($db == null) {
            $DB = Database_Action::getDb();
        } else {
            $DB = $db;
        }
        $this->sql_query = $query;
        $this->page_name = $page_holder;

        if (isset($_GET[$page_holder])) {
            $page = $_GET[$page_holder];
        } elseif (isset($_POST[$page_holder])) {
            $page = $_POST[$page_holder];
        } else {
            $page = '';
        }

        if (empty($page) || !is_numeric($page)) $page = 1;
        $this->current_page_number = $page;

        $this->number_of_rows_per_page = $max_rows;

        $pos_to = strlen($this->sql_query);
        $pos_from = strrpos(strtolower($this->sql_query), ' from', 0);

        //        echo $this->sql_query,'<br />',$pos_from;

        $pos_group_by = stripos($this->sql_query, ' group by', $pos_from);
        if (($pos_group_by < $pos_to) && ($pos_group_by != false)) $pos_to = $pos_group_by;

        $pos_having = stripos($this->sql_query, ' having', $pos_from);
        if (($pos_having < $pos_to) && ($pos_having != false)) $pos_to = $pos_having;

        $pos_order_by = stripos($this->sql_query, ' order by', $pos_from);
        if (($pos_order_by < $pos_to) && ($pos_order_by != false)) $pos_to = $pos_order_by;

        if ((stripos($this->sql_query, 'distinct') || stripos($this->sql_query, 'group by')) && $count_key != '*') {
            $count_string = 'distinct ' . $DB->input($count_key);
        } else {
            $count_string = $DB->input($count_key);
        }

        $count_query = ("select count(" . $count_string . ") as total " . substr($this->sql_query, $pos_from, ($pos_to - $pos_from)));
        //		echo $count_query; exit;
        $count_query = $DB->query($count_query);
        $count = $DB->fetch_array($count_query);

        //echo $count['total'];exit;
        $this->number_of_rows = $count['total'];

        $this->number_of_pages = ceil($this->number_of_rows / $this->number_of_rows_per_page);

        if ($this->current_page_number > $this->number_of_pages) {
            $this->current_page_number = $this->number_of_pages;
        }

        $offset = ($this->number_of_rows_per_page * ($this->current_page_number - 1));

        $this->sql_query .= " limit " . max($offset, 0) . ", " . $this->number_of_rows_per_page;

        //为兼容原系统的功能（特别是后台），$query的最新值必须要设置
        $query = $this->sql_query;
    }

    /* class functions */

    /**
     * 显示翻页链接数据(后台或对样式无要求的可用)
     * @param int $max_page_links 每页面最多显示多少个页码
     * @param string $parameters 生成href时要排除的GET参数名称
     * @param bool $for_seo 是否开启seo模式，默认否
     * @return string
     */
    function display_links($max_page_links, $parameters = '', $for_seo = false) {
        $array = $this->display_links_array($max_page_links, $parameters, false);
        $display_links_string = '';
        $class = 'class="pageResults"';
        if($array){
            if($array['first_href']){
                $display_links_string .= '<a '.$class.' href="'.$array['first_href'].'" title="第一页"><u>|&lt;</u></a>&nbsp;&nbsp;';
            }
            if($array['previous_href']){
                $display_links_string .= '<a '.$class.' href="'.$array['previous_href'].'" title="上一页"><u>&lt;&lt;</u></a>&nbsp;&nbsp;';
            }
            if($array['previous_x_page']){	//前X页
                $display_links_string .= '<a '.$class.' href="'.$array['previous_x_page']['href'].'" title="'.$array['previous_x_page']['text'].'"><u>...</u></a>&nbsp;&nbsp;';
            }
            for($i=0, $n=sizeof($array['pages_list']); $i<$n; $i++){	//第n页集合
                if($array['pages_list'][$i]['selected']==1){
                    $display_links_string .= '<strong>' . $array['pages_list'][$i]['text'] . '</strong>&nbsp;&nbsp;';
                }else{
                    $display_links_string .= '<a '.$class.' href="'.$array['pages_list'][$i]['href'].'" title="'.$array['previous_x_page']['text'].'"><u>'.$array['pages_list'][$i]['text'].'</u></a>&nbsp;&nbsp;';
                }
            }
            if($array['next_x_page']){	//下X页
                $display_links_string .= '<a '.$class.' href="'.$array['next_x_page']['href'].'" title="'.$array['next_x_page']['text'].'"><u>...</u></a>&nbsp;&nbsp;';
            }
            if($array['next_href']){
                $display_links_string .= '<a '.$class.' href="'.$array['next_href'].'" title="下一页"><u>&gt;&gt;</u></a>&nbsp;&nbsp;';
            }
            if($array['last_href']){
                $display_links_string .= '<a '.$class.' href="'.$array['last_href'].'" title="最后一页"><u>&gt;|</u></a>&nbsp;&nbsp;';
            }
        }
        return $display_links_string;
    }

    /**
     * 将翻页数据输出为数组
     * @param int    $max_page_links 每页面最多显示多少个页码
     * @param string $parameters 生成href时要排除的GET参数名称
     * @param bool   $for_seo 是否开启seo模式，默认是
     *
     * @return array
     */
    function display_links_array($max_page_links, $parameters = '', $for_seo = true) {
        $PHP_SELF     = $_SERVER['PHP_SELF'];
        $request_type = 'NONSSL'; //SSL
        $page         = basename($PHP_SELF);
        $data         = array();
        if (!empty($parameters) && (substr($parameters, -1) != '&'))
            $parameters .= '&';
        //第一页和前一页(在第一页时不显示) button - not displayed on first page
        if ($this->current_page_number > 1) {
            $previous_page_number = $this->current_page_number - 1;
            $page_param           = $this->page_name . '=' . ($this->current_page_number - 1);
            if ($previous_page_number <= 1) {
                $page_param = '';
            }

            $data['previous_href'] = $this->setHref($page, $parameters . $page_param, $request_type, false, false, $for_seo);
            $data['first_href']    = $this->setHref($page, $parameters, $request_type, false, false, $for_seo);
        }
        // check if number_of_pages > $max_page_links
        $cur_window_num = intval($this->current_page_number / $max_page_links);
        if ($this->current_page_number % $max_page_links)
            $cur_window_num++;
        $max_window_num = intval($this->number_of_pages / $max_page_links);
        if ($this->number_of_pages % $max_page_links)
            $max_window_num++;
        // 前$max_page_links页，前n页的计算原则：当前页-$max_page_links页与1的最大值
        if ($cur_window_num > 1) {
            $data['previous_x_page'] = array('text' => '前' . $max_page_links . '页', 'href' => $this->setHref($page, $parameters . $this->page_name . '=' . max(1, ($this->current_page_number - $max_page_links)), $request_type, false, false, $for_seo));
        }
        // 第XX页的按钮集数组page nn button
        $data['pages_list'] = array();
        $start              = max(1, ($this->current_page_number - intval($max_page_links / 2)));
        $end                = min(max(($this->current_page_number - 1 + $max_page_links - intval($max_page_links / 2)), $max_page_links), $this->number_of_pages);
        for ($jump_to_page = $start; $jump_to_page <= $end; $jump_to_page++) {
            if ($jump_to_page == $this->current_page_number) {
                $data['pages_list'][] = array('href' => '', 'text' => $jump_to_page, 'selected' => '1');    //当前选中的页面添加一个selected属性并把href设置为空
            } else {
                $page_param           = ($jump_to_page == 1) ? '' : $this->page_name . '=' . $jump_to_page;
                $data['pages_list'][] = array('href' => $this->setHref($page, $parameters . $page_param, $request_type, false, false, $for_seo), 'text' => $jump_to_page);
            }
        }
        // 下$max_page_links页，下n页的计算原则：当前页+$max_page_links页与总页数的最小值
        if ($cur_window_num < $max_window_num) {
            $data['next_x_page'] = array('text' => '后' . $max_page_links . '页', 'href' => $this->setHref($page, $parameters . $this->page_name . '=' . min(($this->current_page_number + $max_page_links), $this->number_of_pages), $request_type, false, false, $for_seo));
        }
        // 下一页和最后一页 next button
        if (($this->current_page_number < $this->number_of_pages) && ($this->number_of_pages != 1)) {
            $data['next_href'] = $this->setHref($page, $parameters . $this->page_name . '=' . ($this->current_page_number + 1), $request_type, false, false, $for_seo);
            $data['last_href'] = $this->setHref($page, $parameters . $this->page_name . '=' . $this->number_of_pages, $request_type, false, false, $for_seo);
        }
        return $data;
    }
    /**
     * 自动根据前后台环境设置页面连接
     */
    private function setHref(){
        $numargs = func_num_args();
        $arg_list = func_get_args();
        if($numargs < 2 ){
            throw \Z::Error('翻页链接页面设置错误！参数太少。');
        }
        /*$HT = defined('IS_BACKSTAGE') ? IS_BACKSTAGE : false; //后台标识
        if($HT === true){
            return Html::href_link_admin($arg_list[0], $arg_list[1], $arg_list[2]);
        }*/
        return Html::href_link($arg_list[0], $arg_list[1], $arg_list[2], $arg_list[3], $arg_list[4], $arg_list[5]);
    }
    /**
     * 数据记录统计消息display number of total products found
     * @param string $text_output 被替换的字符串 ，此字符串有有3个%d
     * @param string $type 返回的数据类型，array为返回数组。
     * @example 显示 41 至 80 (总共 677 条记录)
     * @return string 返回统计消息的文字
     */
    function display_count($text_output, $type='') {
        if(!$text_output) $text_output = '显示 %d 至 %d (总共 %d 条记录)';
        $to_num = ($this->number_of_rows_per_page * $this->current_page_number);
        if ($to_num > $this->number_of_rows) $to_num = $this->number_of_rows;

        $from_num = ($this->number_of_rows_per_page * ($this->current_page_number - 1));

        if ($to_num == 0) {
            $from_num = 0;
        } else {
            $from_num++;
        }
        if($type == 'array'){
            $this->current_start_number = $from_num;
            $this->current_end_number = $to_num;
            return array('from_num'=>$from_num, 'to_num'=>$to_num, 'number_of_rows'=>$this->number_of_rows);
        }
        return sprintf($text_output, $from_num, $to_num, $this->number_of_rows);
    }
    /**
     * 返回记录结果统计信息数组
     * @example return array('from_num'=>当页起始行数, 'to_num'=>当页最后行数, 'number_of_rows'=>总记录数)
     * @return array 返回包含有起止行数和总记录数的信息
     */
    public function getResultsStatistics(){
        return $this->display_count('', 'array');
    }
}
